//aaa1
#include "init.h"


///////////////////////////////////////////////////////
////	ABC LONG				DEFINITION CODE HERE
///////////////////////////////////////////////////////


Player* Closet_Player; 
Player* Opnt_Closet_Player;
Player* Support_Player;
Player* Receive_Player;



void Calc_Distant2Ball(FootBallMatch* _this);
Player* FindRecivePlayer(std::vector<Player*>,std::vector<Player*>);
bool canPass(std::vector<Player*> team,Player* player);
bool beThreaten(std::vector<Player*> team,Player* player);
bool Is_Control_Ball();


///////////////////////////////////////////////////////
////					DON'T TOUCH MAIN
///////////////////////////////////////////////////////
int main(int argc, char* argv[]) {
	srand ( time(NULL) );

	Get_BOT_Name(argc,argv);
	FootBallMatch::Update = &AI_Update;
	FootBallMatch::Init = &AI_Init;
	FootBallMatch::Penalty = &AI_SetPenalty;
	FootBallMatch::EndGame = &AI_EndGame;
	AppClientHandlerPtr temp(new AppClientHandler());
	s_con_handler = temp;
	p_Fooball_Match = new FootBallMatch(LEFT,bot_table_x,bot_table_y,bot_name,bot_avatar);
	boost::thread thr_cGame(boost::bind(&FootBallMatch::Run,p_Fooball_Match,s_con_handler));
	Connection();
	thr_cGame.join();
	delete p_Fooball_Match;
    return 0;
}






///////////////////////////////////////////////////////
////					DECLARATION CODE HERE
///////////////////////////////////////////////////////
bool BallInOwnerPlace(FootBallMatch* _this)
{
	vector2d vBall2Goal = _this->GameBall()->Pos() - _this->Goal_Team();
	return vBall2Goal.Length()<(PITCH_WIDTH/2);
}


Player* MyBackRight;
Player* opntBackRight;
Player* MyBackLeft;
Player* opntBackLeft;
Player* MyForwardLeft;
Player* opntForwardLeft;
Player* MyForwardRight;
Player* opntForwardRight;
Player* forward;
Player* back;
Player* centerLeft;
Player* centerRight;
void AI_Init(FootBallMatch* team) 
{
	
	std::cout<<"\nINIT YOUR BOT HERE!!!"<<std::endl;
}
void AI_SetPenalty(FootBallMatch* _this){
		std::cout<<"\nGAME PENALTY!\n";
		for(int i = 0; i<20;i++)
		{
			penalty_arr[i] = int(float(rand()%300)/100);
		}
		_this->SetPenaltyArray(penalty_arr);
}
bool isNearThan(vector2d p,vector2d a, vector2d b)
{
	vector2d c = a-p;
	vector2d d = b-p;
	return (c.Length()-d.Length()>0);
}
void AI_EndGame(FootBallMatch* _this)
{
	std::cout<<"\nGAME EXIT,  SCORE:"<<_this->Score().x<<" : "<<_this->Score().y<<std::endl;
}

void FindBall(Player* Left, Player* Center, Player* Right, FootBallMatch* _this)
{
	
}
	int sign = 0;
void BackToDefault(Player* a,FootBallMatch* _this)
{

	
	switch(a->ID())
	{
		case LEFT_HAFT_BACK : 
			{
				//a->SetTarget(vector2d(PITCH_CENTER_POINT.x 
			}
			break;

		case RIGHT_HAFT_BACK : break;
		case LEFT_HAFT_FORWARD : break;
		case RIGHT_HAFT_FORWARD : break;
	}
	
}
void KickBall(Player* a, FootBallMatch* _this)
{

}
bool findAllPlayer = false;
float Ball2DefaultPos(Player* a, FootBallMatch* _this)
{
	vector2d k = a->DefaultPos() - _this->GameBall()->Pos();
	return k.Length();
}
float Target2Pos(Player* a)
{
	vector2d k = a->Target() - a->Pos();
	return k.Length();
}

void AI_Update(FootBallMatch* _this)
{
	std::cout<<"\nGAME UPDATE!\n";
	_this->Debug_Console_Output(true);
	std::vector<Player*>::iterator it;
	std::vector<Player*> myTeam		=	_this->OwnerTeam();
	std::vector<Player*> opntTeam	=	_this->OpntTeam();
	int revertHead = -1;
	Closet_Player = NULL;
	Opnt_Closet_Player = NULL;
	Support_Player = NULL;
	Receive_Player = NULL;
	Player* GoalKeeper = myTeam.at(0);
	
	
	Receive_Player =  GoalKeeper;
	Calc_Distant2Ball(_this);
	sign = (_this->TeamPlace()== LEFT)? -1: 1;
	if(!findAllPlayer)
	{
		
		for(it = myTeam.begin();  it != myTeam.end();it++ )
		{
			switch((*it)->ID())
				{
					case LEFT_HAFT_BACK : 
						MyBackLeft = *it;
						back = *it;
						back->SetDefaultPos(PITCH_CENTER_POINT + vector2d(- sign * PITCH_WIDTH/2.5f,0.0f));
						break;
					case RIGHT_HAFT_BACK : 
						MyBackRight = *it;
						centerRight = *it;
						centerRight->SetDefaultPos(PITCH_CENTER_POINT + vector2d(0.0f,-PITCH_HEIGHT/4.0f));
						break;
					case LEFT_HAFT_FORWARD : 
						MyForwardLeft = *it;
						centerLeft = *it;
						centerLeft->SetDefaultPos(PITCH_CENTER_POINT + vector2d(0.0f,PITCH_HEIGHT/4.0f));
						break;
					case RIGHT_HAFT_FORWARD : 
						MyForwardRight = *it;
						forward = *it;
						forward->SetDefaultPos(PITCH_CENTER_POINT + vector2d( sign * PITCH_WIDTH/2.5f,0.0f));
						break;
				}
			
		}
		findAllPlayer = true;
	}
	for(it = myTeam.begin();  it != myTeam.end();it++ )
	{
		
		
		if((*it)->Dist2Ball() < k_control_len)
		{
			if((_this->GameBall()->Pos().x - PITCH_CENTER_POINT.x)*sign > 0)
			{
				(*it)->SetTarget(vector2d((*it)->Pos().x - 200.0f*sign, PITCH_HEIGHT));
				if(Target2Pos(*it)> PITCH_HEIGHT/2.0f)
				{
					(*it)->SetTarget(vector2d((*it)->Pos().x - 200.0f*sign, 0));
				}
			}
			else
			{
				(*it)->SetTarget(_this->Goal_Opnt());
			}
			(*it)->SetForce(k_kick_foce);
			(*it)->SetAction(KICK);
			break;
		}
		else
		{
			
			if((*it) == Closet_Player)
			{
					(*it)->SetTarget(_this->GameBall()->Pos());
					(*it)->SetForce(k_move_foce);
					(*it)->SetAction(MOVE);
					continue;
			}
		}

			vector2d v_attarget= (*it)->Target() - (*it)->Pos();
			if(v_attarget.Length()<15) //This code to hold the Player stand at the Target.
			{
					(*it)->SetTarget(_this->GameBall()->Pos());
					(*it)->SetForce(0);
					(*it)->SetAction(MOVE);
					continue;
			}
		
		if(Ball2DefaultPos((*it), _this) < PITCH_WIDTH/4.0f || (*it)->Dist2Ball() < 100.0f)
		{
			(*it)->SetTarget(_this->GameBall()->Pos());
			(*it)->SetForce(k_move_foce);
			(*it)->SetAction(MOVE);
			continue;
		}
		else if((*it) != GoalKeeper)
		{
				
			vector2d direction = _this->GameBall()->Pos() - (*it)->DefaultPos();
			
			(*it)->SetTarget((*it)->DefaultPos() + direction.Norm()*100);
			
			(*it)->SetForce(k_move_foce);
			(*it)->SetAction(MOVE);
		}
		else
		{
			(*it)->SetTarget((*it)->DefaultPos());
			
			(*it)->SetForce(k_move_foce);
			(*it)->SetAction(MOVE);
		}
		
		
	}
	if(_this->RemainTime() == 0)
	{
		findAllPlayer = false;
	}

}


/*************************************************
*	Calculate the Length to ball of Team players
***************************************************/
void Calc_Distant2Ball(FootBallMatch* _this )
{
	vector<Player*> team = _this->OwnerTeam();
	vector<Player*> opnt_team = _this->OpntTeam();
	vector2d ball(_this->GameBall()->Pos());
	std::vector<Player*>::iterator player;
	double min_distant = PITCH_WIDTH;
	vector2d vector2ball;
	for(player = team.begin();player != team.end();player++)
	{
		vector2ball = ball - (*player)->Pos();
		(*player)->SetDist2Ball(vector2ball.Length());
		if(vector2ball.Length() <= min_distant )
		{
			Closet_Player = (*player);
			min_distant = vector2ball.Length();
		}
	}
	min_distant = PITCH_WIDTH;
	for(player = opnt_team.begin();player != opnt_team.end();player++)
	{
		vector2ball = ball - (*player)->Pos();
		(*player)->SetDist2Ball(vector2ball.Length());
		if(vector2ball.Length() <= min_distant )
		{
			Opnt_Closet_Player = (*player);
			min_distant = vector2ball.Length();
		}
	}

}
/*************************************************
*	Find the player to recieve the ball
***************************************************/
Player* FindRecivePlayer(std::vector<Player*> team,std::vector<Player*> opnt_team)
{
	std::vector<Player*>::iterator player = team.end();
	while(player != team.begin())
	{
		player--;
		vector2d dist2Closet = Closet_Player->Pos() - (*player)->Pos();
		if((*player) == Closet_Player ) continue;
		if(!beThreaten(opnt_team, *player)
			&& canPass(opnt_team, *player)
			&& dist2Closet.Length()>100)
		{
			return *player;
		}
	}
	return Closet_Player!=*(team.begin()) ? *(team.end()-1): *(team.end()-2);
}
/*************************************************
*	Check the path of the ball if interaction with the any opponent player's control-region
***************************************************/
bool canPass(std::vector<Player*> opnt_team,Player* player)
	{
		vector2d vReceiver = player->Pos();
		vector2d vControler = Closet_Player->Pos();
		vector<Player*>::iterator opnt_it;
		for(opnt_it= opnt_team.begin();opnt_it != opnt_team.end(); opnt_it++)
		{
			if((*opnt_it)->Pos().InsideRegion(vReceiver,vControler)	)return false;
		}
		return true;
	}

/*************************************************
*	Return TRUE if has any opponent player inside the Range of player 
*	The Range define radius = k_threaten_len
***************************************************/
bool beThreaten(std::vector<Player*> Opnt_team,Player* player){
		
		vector2d vdist;
		vector<Player*>::iterator opnt_it;
		for(opnt_it= Opnt_team.begin();opnt_it != Opnt_team.end(); opnt_it++)
		{
			vdist = (*opnt_it)->Pos() - player->Pos();
			if(vdist.Length() <= k_threaten_len) return true;
		}
		return false;

	}

/*************************************************
*	Check which team is controling the Ball to set Team status Attack or Defend
***************************************************/
bool Is_Control_Ball(){
	if(Opnt_Closet_Player->Dist2Ball() > Closet_Player->Dist2Ball()) 
		return true;
	return false;
}

///////////////////////////////////////////////////////
////					THE END
///////////////////////////////////////////////////////
